#include "ntc_drv.h"


/**
 * @desc  : ntc 引脚配置
 * @date  : 2025-09-27
 * @author: AnRui
 * @note  :
 */
static void ntc_gpio_init(void)
{
    rcu_periph_clock_enable(NTC_GPIO_RCU);
    gpio_init(NTC_GPIO, GPIO_MODE_AIN, GPIO_OSPEED_10MHZ, NTC_GPIO_PIN);
}

/**
 * @desc  : 外设ADC初始化
 * @date  : 2025-09-26
 * @author: AnRui
 * @note  :
 */
static void ntc_adc_init(void)
{
    rcu_periph_clock_enable(NTC_ADC_X_RCU);
    /*重置adc*/
    adc_deinit(NTC_ADC_X);
    /* 设置分频系数；*/
    rcu_adc_clock_config(NTC_ADC_X_CLOCK_DIV);
    /* 设置独立模式；*/
    adc_mode_config(ADC_MODE_FREE);
    /* 设置分辨率 12位 4095*/
    adc_resolution_config(NTC_ADC_X, ADC_RESOLUTION_12B);
    /* 设置连续模式；*/
    adc_special_function_config(NTC_ADC_X, ADC_CONTINUOUS_MODE, DISABLE);
    /* 设置扫描模式；*/
    adc_special_function_config(NTC_ADC_X, ADC_SCAN_MODE, DISABLE);
    /* 设置数据对齐；*/
    adc_data_alignment_config(NTC_ADC_X, ADC_DATAALIGN_RIGHT);
    /* 常规通道个数 */
    adc_channel_length_config(NTC_ADC_X, ADC_REGULAR_CHANNEL, 1);
    /* 常规规则 : 指定ADC 外设  通道的优先级  配置的 ADC 通道   采样时间(周期)*/
    adc_regular_channel_config(NTC_ADC_X, 0, NTC_ADC_X_CHANNEL, NTC_ADC_X_TRANS_CYCLES);
    /* 设置选择哪一个触发源: 软件触发*/
    adc_external_trigger_source_config(NTC_ADC_X, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
    /* 使能触发；*/
    adc_external_trigger_config(NTC_ADC_X, ADC_REGULAR_CHANNEL, ENABLE);
    /* 使能ADC；*/
    adc_enable(NTC_ADC_X);
    // 等待ADC稳定（约10-20us）
    DwtDelayNus(20);
    /* 内部校准；*/
    adc_calibration_enable(NTC_ADC_X);
}

/**
 * @desc  : ntc驱动初始化
 * @date  : 2025-09-27
 * @author: AnRui
 * @note  :
 */
bool ntc_drv_init(void)
{
    ntc_gpio_init();
    ntc_adc_init();
    return true;
}

/**
 * @desc  : 触发ADC转换
 * @date  : 2025-09-29
 * @author: AnRui
 * @note  :
 */
static void ntc_adc_triger(void)
{
    adc_flag_clear(NTC_ADC_X, ADC_FLAG_EOC);
    adc_software_trigger_enable(NTC_ADC_X, ADC_REGULAR_CHANNEL);
}

/**
 * @desc  : ntc计算温度值
 * @date  : 2025-09-29
 * @author: AnRui
 * @return: float
 * @note  : 把adc的值转成对应的电压 并计算当前热敏电阻的值
 *          通过T = 1 / ( (1/B)×log(Rt/Rp) + 1/T0 )  计算当前温度
 *          扩大1000倍返回 这样能保证小数点后3位能保存
 */
static int ntc_cala_temperatrue(void)
{
    uint16_t adc_value;
    float cur_v, cur_r, cur_t, ref_v = 3.3f;
    adc_value = adc_regular_data_read(NTC_ADC_X);
    // 计算电压（全单精度运算）
    cur_v = adc_value * ref_v / 4096.0f;
    // 计算 NTC 电阻（10000.0f 明确为单精度，避免整数提升）
    cur_r = (cur_v * 10000.0f) / (ref_v - cur_v);
    // 关键修改：logf() + 所有常量加 f，彻底消除类型转换
    cur_t = (NTC_B / (log(cur_r / NTC_RP) + (NTC_B / NTC_T0))) - 273.15f;
    return (int)(cur_t * 1000);
}


/**
 * @desc  : 触发ntc采样并获取温度值
 * @date  : 2025-11-05
 * @author: AnRui
 * @return: int
 * @note  : 返回值是测量值的1000倍
 *          返回值小于0代表获取失败
 */
int ntc_trigger_and_get_temp(void)
{
    int result = -1;
    int time_out_us = NTE_DEFAULT_TIMEOUT;
    ntc_adc_triger();
    while (time_out_us) {
        if (adc_flag_get(NTC_ADC_X, ADC_FLAG_EOC) == SET) {
            result = ntc_cala_temperatrue();
            break;
        }
        time_out_us--;
        NTE_DELAY_US(1);
    }
    return result;
}
